package spring.cloud.tasks.executor.executor;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import spring.cloud.tasks.common.task_item_allot.Executor;
import spring.cloud.tasks.common.task_item_allot.TaskItem;
import spring.cloud.tasks.executor.executor.task.execute_runtime_context.TaskItemExecuteRuntimeContext;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
 * 实时维护当前执行器任务和任务片信息。
 * 那么就可以主动或者被动通知任务调度启动或停止任务调度以及任务分片信息的添加或者删除。hi
 * <p>
 * 两种机制 1ZK监听机制 2启动线程定时去拉取。两者需要给定一个版本。在获取数据的时候，需要进行加锁保持同步。
 * 1ZK监听机制优于2启动线程定时去拉取。
 */

/**
 * 任务信息(包括待执行的 正在执行的  执行成功的  执行失败的  执行异常的 执行超时的 以及其他情况)
 */
@Slf4j
public class TaskMap {
    public ConcurrentHashMap<String/*任务id*/,//
            ConcurrentHashMap<String/*实例id*/,//
                    ConcurrentHashMap<String/*任务阶段*/, //
                            ConcurrentHashMap<String/*任务阶段.类型*/, //
                                    ConcurrentHashMap<String/*任务阶段.类型.index*/, //
                                            TaskItem>>>>> taskIdToTaskItemCollectionMap = new ConcurrentHashMap<>();//
    public ConcurrentHashMap<String/*任务id*/,//
            ConcurrentHashMap<String/*实例id*/,//
                    ConcurrentHashMap<String/*任务阶段*/, //
                            ConcurrentHashMap<String/*任务阶段.类型*/, //
                                    List<Integer/*任务分片信息*/>>>>> taskIdToTaskItemIndexListCollectionMap = new ConcurrentHashMap<>();

    /**
     * 更新最新的任务分片信息
     *
     * @param onlineExecutor
     */
    public void updateLastTaskItemInfo(Executor onlineExecutor) {
        ConcurrentHashMap<String/*任务id*/,//
                ConcurrentHashMap<String/*实例id*/,//
                        ConcurrentHashMap<String/*任务阶段*/, //
                                ConcurrentHashMap<String/*任务阶段.类型*/, //
                                        ConcurrentHashMap<String/*任务阶段.类型.index*/, //
                                                TaskItem>>>>> taskIdToTaskItemCollectionMap = new ConcurrentHashMap<>();//
        ConcurrentHashMap<String/*任务id*/,//
                ConcurrentHashMap<String/*实例id*/,//
                        ConcurrentHashMap<String/*任务阶段*/, //
                                ConcurrentHashMap<String/*任务阶段.类型*/, //
                                        List<Integer/*任务分片信息*/>>>>> taskIdToTaskItemIndexListCollectionMap = new ConcurrentHashMap<>();

        //针对最新的任务分片信息进行分配
        List<TaskItem> assignedTaskItemList = onlineExecutor.getTaskItemList();
        for (TaskItem taskItem : assignedTaskItemList) {
            String taskId = taskItem.getTaskId();
            String taskInstanceId = taskItem.getTaskInstanceId();
            String taskStage = taskItem.taskStage;
            String taskStage$type = taskItem.getTaskStage$type();
            int taskStage$type$index = taskItem.getTaskStage$type$index();
            String taskStage$type$indexString = String.valueOf(taskStage$type$index);
            String taskItemId = TaskItemExecuteRuntimeContext.getTaskItemId(taskId, taskInstanceId, taskStage, taskStage$type, taskStage$type$index);
            //
            taskIdToTaskItemCollectionMap.putIfAbsent(taskId, new ConcurrentHashMap<>());
            taskIdToTaskItemIndexListCollectionMap.putIfAbsent(taskId, new ConcurrentHashMap<>());
            ConcurrentHashMap taskInstanceIdToTaskItemCollectionMap = taskIdToTaskItemCollectionMap.get(taskId);
            ConcurrentHashMap taskInstanceIdToTaskItemIndexListCollectionMap = taskIdToTaskItemIndexListCollectionMap.get(taskId);
            //
            taskInstanceIdToTaskItemCollectionMap.putIfAbsent(taskInstanceId, new ConcurrentHashMap<>());
            taskInstanceIdToTaskItemIndexListCollectionMap.putIfAbsent(taskInstanceId, new ConcurrentHashMap<>());
            ConcurrentHashMap taskStageToTaskItemCollectionMap = (ConcurrentHashMap) taskInstanceIdToTaskItemCollectionMap.get(taskInstanceId);
            ConcurrentHashMap taskStageToTaskItemIndexListCollectionMap = (ConcurrentHashMap) taskInstanceIdToTaskItemIndexListCollectionMap.get(taskInstanceId);
            //
            taskStageToTaskItemCollectionMap.put(taskStage, new ConcurrentHashMap<>());
            taskStageToTaskItemIndexListCollectionMap.put(taskStage, new ConcurrentHashMap<>());
            ConcurrentHashMap taskStage$typeToTaskItemCollectionMap = (ConcurrentHashMap) taskStageToTaskItemCollectionMap.get(taskStage);
            ConcurrentHashMap taskStage$typeToTaskItemIndexListCollectionMap = (ConcurrentHashMap) taskStageToTaskItemIndexListCollectionMap.get(taskStage);
            //
            taskStage$typeToTaskItemCollectionMap.put(taskStage$type, new ConcurrentHashMap<>());
            taskStage$typeToTaskItemIndexListCollectionMap.put(taskStage$type, new CopyOnWriteArrayList<>());
            ConcurrentHashMap taskStage$type$indexToTaskItemMap = (ConcurrentHashMap) taskStage$typeToTaskItemCollectionMap.get(taskStage$type);
            CopyOnWriteArrayList taskItemIndexList = (CopyOnWriteArrayList) taskStage$typeToTaskItemIndexListCollectionMap.get(taskStage$type);
            //
            taskStage$type$indexToTaskItemMap.put(taskStage$type$indexString, taskItem);
            taskItemIndexList.add(taskStage$type$indexString);
            //最后进行计算是否【相同实例存在多个阶段并存的情况】，只给提示不进行处理。
            if (taskStageToTaskItemCollectionMap.size() > 1) {
                log.error("请开发人员和运维人员注意:相同实例存在多个阶段并存的情况,具体详细信息如下" + JSON.toJSONString(taskStageToTaskItemCollectionMap));
            }

        }
        this.taskIdToTaskItemCollectionMap = taskIdToTaskItemCollectionMap;
        this.taskIdToTaskItemIndexListCollectionMap = taskIdToTaskItemIndexListCollectionMap;
    }

    /**
     * 判断是否有没有创建任务上下文可以使用这个。
     *
     * @param taskId
     * @param taskInstanceId
     * @param taskStage
     * @param taskStage$type
     * @param taskStage$type$index
     * @return
     */
    public boolean isAssigned(String taskId,
                              String taskInstanceId,
                              String taskStage,
                              String taskStage$type,
                              Integer taskStage$type$index) {
        ConcurrentHashMap<String, ConcurrentHashMap<String, ConcurrentHashMap<String, List<Integer>>>> a = taskIdToTaskItemIndexListCollectionMap.get(taskId);
        if (a == null) {
            return false;
        }
        ConcurrentHashMap<String, ConcurrentHashMap<String, List<Integer>>> b = a.get(taskInstanceId);
        if (b == null) {
            return false;
        }
        ConcurrentHashMap<String, List<Integer>> c = b.get(taskStage);
        if (c == null) {
            return false;
        }
        List<Integer> d = c.get(taskStage$type);
        if (d == null) {
            return false;
        }
        return d.contains(taskStage$type$index);

    }

    /**
     * 创建任务上下文可以使用这个
     *
     * @param taskItemExecuteRuntimeContext
     * @return
     */
    public boolean isAssigned(TaskItemExecuteRuntimeContext taskItemExecuteRuntimeContext) {
        String taskId = taskItemExecuteRuntimeContext.getTaskId();
        String taskInstanceId = taskItemExecuteRuntimeContext.getTaskInstanceId();
        String taskStage = taskItemExecuteRuntimeContext.getTaskStage();
        String taskStage$type = taskItemExecuteRuntimeContext.getTaskStage$type();
        Integer taskStage$type$index = taskItemExecuteRuntimeContext.getTaskStage$type$index();
        ConcurrentHashMap<String, ConcurrentHashMap<String, ConcurrentHashMap<String, List<Integer>>>> a = taskIdToTaskItemIndexListCollectionMap.get(taskId);
        if (a == null) {
            return false;
        }
        ConcurrentHashMap<String, ConcurrentHashMap<String, List<Integer>>> b = a.get(taskInstanceId);
        if (b == null) {
            return false;
        }
        ConcurrentHashMap<String, List<Integer>> c = b.get(taskStage);
        if (c == null) {
            return false;
        }
        List<Integer> d = c.get(taskStage$type);
        if (d == null) {
            return false;
        }
        return d.contains(taskStage$type$index);

    }

    public ConcurrentHashMap<String, ConcurrentHashMap<String, ConcurrentHashMap<String, ConcurrentHashMap<String, TaskItem>>>> getTaskTaskItemMap(String taskId) {
        if (!taskIdToTaskItemCollectionMap.containsKey(taskId)) {
            return new ConcurrentHashMap<>();
        }
        return taskIdToTaskItemCollectionMap.get(taskId);
    }


}
